using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Transactions;

using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;

namespace EntLibContrib.PolicyInjection.CallHandlers
{
    /// <summary>
    /// An attribute used to apply the <see cref="TransactionScopeCallHandler"/> to the target.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class TransactionScopeCallHandlerAttribute : HandlerAttribute
    {
        private bool complete = true;
        private TransactionScopeOption scopeOption;
        private TimeSpan timeout = TimeSpan.Zero;
        private IsolationLevel isolationLevel;
        private EnterpriseServicesInteropOption interopOption;

        [NonSerialized]
        private TimeSpanConverter timeSpanConverter = new TimeSpanConverter();

        /// <summary>
        /// Creates a new TransactionScopeCallHandlerAttribute
        /// </summary>
        public TransactionScopeCallHandlerAttribute()
        {
        }

        /// <summary>
        /// Creates a new TransactionScopeCallHandlerAttribute
        /// </summary>
        /// <param name="scopeOption">Scope Option</param>
        public TransactionScopeCallHandlerAttribute(TransactionScopeOption scopeOption)
        {
            this.scopeOption = scopeOption;
        }

        /// <summary>
        /// Creates a new TransactionScopeCallHandlerAttribute
        /// </summary>
        /// <param name="scopeOption">Scope Option</param>
        /// <param name="isolationLevel">Isolation Level</param>
        public TransactionScopeCallHandlerAttribute(IsolationLevel isolationLevel)
        {
            this.isolationLevel = isolationLevel;
        }

        /// <summary>
        /// Creates a new TransactionScopeCallHandlerAttribute
        /// </summary>
        /// <param name="scopeOption">Scope Option</param>
        /// <param name="isolationLevel">Isolation Level</param>
        public TransactionScopeCallHandlerAttribute(TransactionScopeOption scopeOption, IsolationLevel isolationLevel)
        {
            this.scopeOption = scopeOption;
            this.isolationLevel = isolationLevel;
        }

        /// <summary>
        /// Gets or Sets whether the handler will complete the TransactionScope on success. 
        /// </summary>
        public bool Complete
        {
            get { return complete; }
            set { complete = value; }
        }

        /// <summary>
        /// Get or sets the Scope Option used by the handler.
        /// </summary>
        /// <value>Scope Option.</value>
        public TransactionScopeOption ScopeOption
        {
            get { return scopeOption; }
            set { scopeOption = value; }
        }

        /// <summary>
        /// Get or sets the Timeout used by the handler.
        /// </summary>
        /// <value>Scope Option.</value>
        public string Timeout
        {
            get { return timeSpanConverter.ConvertToString(timeout); }
            set { timeout = (TimeSpan)timeSpanConverter.ConvertFromString(value); }
        }

        /// <summary>
        /// Get or sets the Isolation Level used by the handler.
        /// </summary>
        /// <value>Scope Option.</value>
        public IsolationLevel IsolationLevel
        {
            get { return isolationLevel; }
            set { isolationLevel = value; }
        }

        /// <summary>
        /// Get or sets the Scope Opetion used by the handler.
        /// </summary>
        /// <value>Scope Option.</value>
        public EnterpriseServicesInteropOption InteropOption
        {
            get { return interopOption; }
            set { interopOption = value; }
        }

        /// <summary>
        /// Gets the Transaction Options
        /// </summary>
        public TransactionOptions TransactionOptions
        {
            get 
            {
                TransactionOptions options = new TransactionOptions();
                options.Timeout = timeout;
                options.IsolationLevel = IsolationLevel;

                return options;
            }
        }

        /// <summary>
        /// Derived classes implement this method. When called, it
        /// creates a new call handler as specified in the attribute
        /// configuration.
        /// </summary>
        /// <returns>A new call handler object.</returns>
        public override ICallHandler CreateHandler()
        {
            return new TransactionScopeCallHandler(ScopeOption, TransactionOptions, InteropOption, Complete);
        }
    }
}
